diff --git a/i40e/Makefile b/i40e/Makefile
index 81f5ab9..85bfb8c 100644
--- a/i40e/Makefile
+++ b/i40e/Makefile
@@ -10,9 +10,9 @@ ifneq ($(KERNELRELEASE),)
 ccflags-y += -I$(src)
 subdir-ccflags-y += -I$(src)
 
-obj-$(CONFIG_I40E) += i40e.o
+obj-$(CONFIG_I40E) += i40e$(NETMAP_DRIVER_SUFFIX).o
 
-i40e-y := i40e_main.o \
+i40e$(NETMAP_DRIVER_SUFFIX)-y := i40e_main.o \
 	i40e_ethtool.o \
 	i40e_adminq.o \
 	i40e_common.o \
@@ -28,14 +28,14 @@ i40e-y := i40e_main.o \
 	i40e_client.o \
 	i40e_virtchnl_pf.o
 
-i40e-$(CONFIG_DCB) += i40e_dcb.o i40e_dcb_nl.o
-i40e-y += kcompat.o
-i40e-y += kcompat_vfd.o
+i40e$(NETMAP_DRIVER_SUFFIX)-$(CONFIG_DCB) += i40e_dcb.o i40e_dcb_nl.o
+i40e$(NETMAP_DRIVER_SUFFIX)-y += kcompat.o
+i40e$(NETMAP_DRIVER_SUFFIX)-y += kcompat_vfd.o
 
 else	# ifneq($(KERNELRELEASE),)
 # normal makefile
 
-DRIVER := i40e
+DRIVER := i40e$(NETMAP_DRIVER_SUFFIX)
 
 # If the user just wants to print the help output, don't include common.mk or
 # perform any other checks. This ensures that running "make help" will always
@@ -89,9 +89,12 @@ ccc: clean
 	@+$(call kernelbuild,modules,coccicheck MODE=report)
 
 # Build manfiles
-manfile:
+manfile: ../${DRIVER}.${MANSECTION}
 	@gzip -c ../${DRIVER}.${MANSECTION} > ${DRIVER}.${MANSECTION}.gz
 
+../${DRIVER}.${MANSECTION}:
+	touch $@
+
 # Clean the module subdirectories
 clean:
 	@+$(call kernelbuild,clean)
diff --git a/i40e/i40e_main.c b/i40e/i40e_main.c
index 6750c3c..f6e3fd1 100644
--- a/i40e/i40e_main.c
+++ b/i40e/i40e_main.c
@@ -148,6 +148,11 @@ bool i40e_is_l4mode_enabled(void)
 	return l4mode > L4_MODE_DISABLED;
 }
 
+#if defined(CONFIG_NETMAP) || defined(CONFIG_NETMAP_MODULE)
+#define NETMAP_I40E_MAIN
+#include <i40e_netmap_linux.h>
+#endif
+
 /**
  * i40e_get_lump - find a lump of free generic resource
  * @pf: board private structure
@@ -3619,6 +3624,10 @@ static int i40e_configure_tx_ring(struct i40e_ring *ring)
 	/* cache tail off for easier writes later */
 	ring->tail = hw->hw_addr + I40E_QTX_TAIL(pf_q);
 
+#ifdef DEV_NETMAP
+	i40e_netmap_configure_tx_ring(ring);
+#endif /* DEV_NETMAP */
+
 	return 0;
 }
 
@@ -3672,6 +3681,10 @@ static int i40e_configure_rx_ring(struct i40e_ring *ring)
 	/* set the prefena field to 1 because the manual says to */
 	rx_ctx.prefena = 1;
 
+#ifdef DEV_NETMAP
+	i40e_netmap_preconfigure_rx_ring(ring, &rx_ctx);
+#endif /* DEV_NETMAP */
+
 	/* clear the context in the HMC */
 	err = i40e_clear_lan_rx_queue_context(hw, pf_q);
 	if (err) {
@@ -3700,6 +3713,11 @@ static int i40e_configure_rx_ring(struct i40e_ring *ring)
 	ring->tail = hw->hw_addr + I40E_QRX_TAIL(pf_q);
 	writel(0, ring->tail);
 
+#ifdef DEV_NETMAP
+	if (i40e_netmap_configure_rx_ring(ring))
+		return 0;
+#endif /* DEV_NETMAP */
+
 	i40e_alloc_rx_buffers(ring, I40E_DESC_UNUSED(ring));
 
 	return 0;
@@ -14167,6 +14185,12 @@ int i40e_vsi_release(struct i40e_vsi *vsi)
 	}
 
 	set_bit(__I40E_VSI_RELEASING, vsi->state);
+
+#ifdef DEV_NETMAP
+	if (vsi->netdev_registered)
+		netmap_detach(vsi->netdev);
+#endif
+
 	uplink_seid = vsi->uplink_seid;
 	if (vsi->type != I40E_VSI_SRIOV) {
 		if (vsi->netdev_registered) {
@@ -14539,6 +14563,12 @@ struct i40e_vsi *i40e_vsi_setup(struct i40e_pf *pf, u8 type,
 	    (vsi->type == I40E_VSI_VMDQ2)) {
 		ret = i40e_vsi_config_rss(vsi);
 	}
+
+#ifdef DEV_NETMAP
+	if (vsi->netdev_registered)
+		i40e_netmap_attach(vsi);
+#endif
+
 	return vsi;
 
 err_rings:
diff --git a/i40e/i40e_txrx.c b/i40e/i40e_txrx.c
index e3eb496..509d0e1 100644
--- a/i40e/i40e_txrx.c
+++ b/i40e/i40e_txrx.c
@@ -9,6 +9,10 @@
 #include "i40e_trace.h"
 #include "i40e_prototype.h"
 
+#if defined(CONFIG_NETMAP) || defined (CONFIG_NETMAP_MODULE)
+#include <i40e_netmap_linux.h>
+#endif /* DEV_NETMAP */
+
 static inline __le64 build_ctob(u32 td_cmd, u32 td_offset, unsigned int size,
 				u32 td_tag)
 {
@@ -974,6 +978,11 @@ static bool i40e_clean_tx_irq(struct i40e_vsi *vsi,
 	unsigned int total_bytes = 0, total_packets = 0;
 	unsigned int budget = vsi->work_limit;
 
+#ifdef DEV_NETMAP
+	if (tx_ring->netdev && netmap_tx_irq(tx_ring->netdev, tx_ring->queue_index) != NM_IRQ_PASS)
+		return true;
+#endif /* DEV_NETMAP */
+
 	tx_buf = &tx_ring->tx_bi[i];
 	tx_desc = I40E_TX_DESC(tx_ring, i);
 	i -= tx_ring->count;
@@ -2745,6 +2754,16 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)
 	bool failure = false;
 	struct xdp_buff xdp;
 
+#ifdef DEV_NETMAP
+	if (rx_ring->netdev) {
+		int dummy, nm_irq;
+		nm_irq = netmap_rx_irq(rx_ring->netdev, rx_ring->queue_index, &dummy);
+		if (nm_irq != NM_IRQ_PASS) {
+			return (nm_irq == NM_IRQ_COMPLETED) ? 1 : budget;
+		}
+	}
+#endif /* DEV_NETMAP */
+
 #ifdef HAVE_XDP_BUFF_RXQ
 	xdp.rxq = &rx_ring->xdp_rxq;
 #endif
